/*
 *  Copyright (c) 2013, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

package com.facebook.rebound;

import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;

/**
 * Wrapper class for abstracting away availability of the JellyBean Choreographer. If Choreographer
 * is unavailable we fallback to using a normal Handler.
 */
public class ChoreographerCompat {

    static final long ONE_FRAME_MILLIS = 17;
    private static ChoreographerCompat __instance = new ChoreographerCompat();

    private EventHandler mHandler;

    public static ChoreographerCompat getInstance() {
        return __instance;
    }

    private ChoreographerCompat() {
        mHandler = new EventHandler(EventRunner.getMainEventRunner());
    }

    public void postFrameCallback(FrameCallback callbackWrapper) {
        mHandler.postTask(callbackWrapper.getRunnable(), 0);
    }

    public void postFrameCallbackDelayed(FrameCallback callbackWrapper, long delayMillis) {
        mHandler.postTask(callbackWrapper.getRunnable(), delayMillis + ONE_FRAME_MILLIS);
    }

    public void removeFrameCallback(FrameCallback callbackWrapper) {
        mHandler.removeTask(callbackWrapper.getRunnable());
    }


    /**
     * This class provides a compatibility wrapper around the JellyBean FrameCallback with methods
     * to access cached wrappers for submitting a real FrameCallback to a Choreographer or a Runnable
     * to a Handler.
     */
    public static abstract class FrameCallback {

        private Runnable mRunnable;

        Runnable getRunnable() {
            if (mRunnable == null) {
                mRunnable = new Runnable() {
                    @Override
                    public void run() {
                        doFrame(System.nanoTime());
                    }
                };
            }
            return mRunnable;
        }

        public abstract void doFrame(long frameTimeNanos);
    }
}
